home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr05 / xnot12a.zip / W3MEM.C < prev    next >
C/C++ Source or Header  |  1993-05-20  |  24KB  |  925 lines

  1. #define MEM_C
  2. #ifndef WIN32     /* whole file */
  3. # include "jam.h"
  4. # include "def.h"
  5. # include "proto.h"
  6.  
  7. /* THIS MODULE MUST BE BUILT LARGE MODEL BECAUSE I HAVE
  8. * NOT SET THE PROTOTYPES TO BE FAR FOR PARAMS OR RETURN ADDRESSES
  9. */
  10. # include <memory.h>
  11. /*********************************************************
  12. * Windows memory manglement - local heap list from GlobalAlloc
  13. * for Window 3.1 environment.
  14. */
  15. #ifdef SHARABLE
  16. # define LOCAL extern
  17. #else
  18. # define LOCAL static
  19. #endif
  20.  
  21. #define STATIC static
  22. #define PRODUCTION
  23.  
  24. #define MAX_NEAR 1024
  25. #define W3_MAX_SMALL_BLOCK (8*1024)
  26.  
  27. void W3memLocalInitialize (void);
  28. void W3memLocalTerminate (void);
  29.  
  30. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
  31. +
  32. + This functions are externed if this module built as a DLL, else local
  33. +
  34. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
  35.  
  36. LOCAL void *W3LocalCheck(void);
  37. LOCAL void W3Free(unsigned char *ptr);
  38. LOCAL unsigned char *W3Malloc (unsigned long num_bytes);
  39. LOCAL unsigned char *W3Calloc (unsigned long count, unsigned long num_bytes);
  40. LOCAL unsigned char *W3Realloc (unsigned char *ptr, unsigned long num_bytes);
  41.  
  42. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  43.  * Prototypes and defines needed for private routines 
  44.  *
  45.  * Unit should be a power of two >= the first power of two larger than a 
  46.  * freed block 
  47.  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  48.  
  49. #define W3_MEMBLK_UNIT 16
  50. #define W3_MEMBLK_MASK (~(W3_MEMBLK_UNIT-1))
  51. #define W3_MEMBLK_PREFIX (int)(sizeof(int))
  52. #define W3_MEMBLK_SUFFIX (int)(sizeof(int))
  53. #define W3_MEMBLK_OVERHEAD (int)(W3_MEMBLK_PREFIX + W3_MEMBLK_SUFFIX)
  54.  
  55. #define W3_HEAP_PREFIX \
  56.  (int)(sizeof(int)+sizeof(W3_QueEntry)+W3_MEMBLK_OVERHEAD)
  57.  
  58. #define W3_HEAP_SUFFIX (W3_MEMBLK_OVERHEAD)
  59. #define W3_HEAP_OVERHEAD (W3_HEAP_PREFIX + W3_HEAP_SUFFIX)
  60. #define W3_HEAP_INCREMENT W3_MAX_SMALL_BLOCK + W3_HEAP_OVERHEAD
  61.  
  62. typedef char W3_Boolean;
  63.  
  64. typedef struct _que_entry 
  65. {
  66.   struct _que_entry *next;
  67.   struct _que_entry *prev;
  68. } W3_QueEntry;
  69.  
  70. typedef struct _mem_blk 
  71. {
  72.   int size;        /* Positive - free; Negative - alloc'd */
  73.   W3_QueEntry link;    /* Start of content for alloc'd block */
  74.   int mark;        /* Used only in checking free blocks on the heap */
  75.   /* Not shown here - a 2-byte size field in the last word of the block */
  76. } W3_MemBlk;
  77.  
  78. typedef struct _heap 
  79. {
  80.   int size;
  81.   W3_QueEntry link;
  82.   char guard [W3_MEMBLK_OVERHEAD]; /* Guards are empty alloc'd memblks */
  83.   W3_MemBlk first;
  84.               /* Not shown here - an additional guard at the end of the heap */
  85. } W3_Heap;
  86.  
  87. typedef struct _zone 
  88. {
  89.   W3_QueEntry avail;
  90.   W3_QueEntry heaps;
  91.   W3_QueEntry *cur;
  92.   struct _zone *next;
  93. #ifdef SHAREABLE
  94.   int zone_id;
  95. #endif
  96. } W3_Zone;
  97.  
  98. /* Private only routines - support for external access points only 
  99. */
  100. STATIC W3_MemBlk *W3FormMemBlk(void *, int);
  101. STATIC W3_MemBlk *W3SplitMemBlk(W3_MemBlk *, int);
  102. STATIC W3_Boolean W3JoinMemBlks(W3_MemBlk *, W3_MemBlk *);
  103. STATIC W3_MemBlk *W3FindMemBlk(W3_QueEntry *, int, W3_QueEntry *);
  104. STATIC void W3InsertMemBlk(W3_MemBlk *, W3_QueEntry *);
  105. STATIC void W3RemoveMemBlk(W3_MemBlk *);
  106. STATIC W3_MemBlk *W3NextMemBlk(W3_MemBlk *);
  107. STATIC W3_MemBlk *W3PrevMemBlk(W3_MemBlk *);
  108. STATIC W3_MemBlk *W3CreateHeap(int, W3_QueEntry *);
  109. STATIC void W3DestroyHeap(W3_Heap *);
  110. STATIC W3_Boolean W3HeapIsEmpty(W3_Heap *);
  111. STATIC void *W3LocalMalloc(int size);
  112. STATIC void *W3LocalRealloc(void *curaddr, int newsize);
  113. STATIC void *W3LocalCalloc (int items, int size);
  114. STATIC void W3LocalFree(void *addr);
  115. STATIC int W3LocalSize(void *addr);
  116.  
  117. #ifdef SHAREABLE
  118.   STATIC W3_Zone *W3FindZone(W3_Zone *root, int id);
  119.   STATIC W3_Zone *W3CreateZone (W3_Zone *root, int id);
  120. #else
  121.   STATIC W3_Zone *W3CreateZone (W3_Zone *root);
  122. #endif
  123.  
  124. /* Local type definitions and constants 
  125. */
  126. #define TRUE 1
  127. #define FALSE 0
  128.  
  129. /* w3__zone points to entire memory mgmt structure 
  130. */
  131. #ifdef SHAREABLE
  132.   W3_Zone *w3__zone = NULL;
  133. #else
  134.   static W3_Zone *w3__zone = NULL;
  135. #endif
  136.  
  137. #define W3CheckGlobalInit() {if (w3__zone == NULL) W3memLocalInitialize();}
  138.  
  139.  
  140. /* Macros taking parameters */
  141.  
  142. #define W3_QUEUE_MAKEEMPTY(item) {item.next = &item; item.prev = &item;}
  143. #define W3_ROUNDSIZE(size)\
  144.   (((size)+W3_MEMBLK_UNIT-1) & W3_MEMBLK_MASK)
  145. #define W3_MEMBLK_SIZEADDR(blk,size)\
  146.   ((int *)((char *)(blk)+(size)-W3_MEMBLK_SUFFIX))
  147. #define W3_HEAP_ENDGUARDADDR(heap,size)\
  148.   ((W3_MemBlk *) ((char *)(heap)+(size)-W3_HEAP_SUFFIX))
  149.  
  150.  
  151. /********************* External Initialization points *****************
  152. */
  153. void W3memLocalInitialize (void) /* this call is optional ifndef SHARABLE */
  154. {
  155.   if (w3__zone == NULL)
  156.     {
  157. #ifdef SHAREABLE
  158.       w3__zone = W3CreateZone (w3__zone, GetCurrentTask());
  159. #else
  160.       w3__zone = W3CreateZone (w3__zone);
  161. #endif
  162.     }
  163. }
  164. void W3memLocalTerminate(void)
  165. {
  166.   W3_Heap *heap;
  167.   W3_Zone *zone;
  168.   
  169.   for (zone = w3__zone; zone != NULL; zone = zone->next)
  170.     while (zone->heaps.next != &(zone->heaps))
  171.       {
  172.         heap = (W3_Heap *) ((char *) zone->heaps.next - sizeof(int));
  173.         zone->heaps.next = heap->link.next;
  174.     W3DestroyHeap (heap);
  175.       }
  176.   w3__zone = NULL;
  177. }
  178. /********************* Normally private access points, **********************
  179. */
  180. /* akin to malloc, returns far ptr to memory
  181. */
  182. LOCAL unsigned char *W3Malloc (unsigned long num_bytes)
  183. {
  184.   HANDLE mhnd;
  185.   unsigned char *adr;
  186.   
  187.   W3CheckGlobalInit();
  188.  
  189.   mhnd = 0;
  190.   if (num_bytes < MAX_NEAR )
  191.     adr = W3LocalMalloc ((int)num_bytes);
  192.   else
  193.     {
  194.       mhnd = GlobalAlloc (GMEM_MOVEABLE, num_bytes);
  195.       if (mhnd == 0)
  196.     return NULL;
  197.       adr = (unsigned char *) GlobalLock (mhnd);
  198.     }
  199.   return adr;
  200. }
  201. /* akin to calloc, returns far ptr to memory
  202. */
  203. LOCAL unsigned char *W3Calloc (unsigned long count, unsigned long num_bytes)
  204. {
  205.   HANDLE mhnd;
  206.   unsigned long    real_size;
  207.   unsigned char *adr;
  208.   
  209.   W3CheckGlobalInit();
  210.  
  211.   real_size = count * num_bytes;
  212.   if (real_size < MAX_NEAR )
  213.     adr = W3LocalCalloc ((int) count, (int) num_bytes);
  214.   else
  215.     {
  216.       mhnd = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, real_size);
  217.       if (mhnd == 0) 
  218.     return NULL;
  219.       adr = (unsigned char *) GlobalLock (mhnd);
  220.     }
  221.   return adr;
  222. }
  223. /* akin to realloc, returns far ptr to memory
  224. */
  225. LOCAL unsigned char *W3Realloc (unsigned char *ptr, unsigned long num_bytes)
  226. {
  227.   HANDLE mhnd,mhnd2;
  228.   char *adr2;
  229.   unsigned long move_len;
  230.   
  231.   W3CheckGlobalInit();
  232.  
  233.   if (LOWORD((long)ptr) != 0) /* If memory is not global */
  234.     {
  235.       if (num_bytes < MAX_NEAR ) /* Both old and new are local handles */
  236.     ptr = W3LocalRealloc (ptr, (int) num_bytes);
  237.       else
  238.     {
  239.       move_len = W3LocalSize (ptr);
  240.       if ((unsigned long) num_bytes < move_len)
  241.         move_len = num_bytes;
  242.       
  243.       mhnd2 = GlobalAlloc (GMEM_MOVEABLE, num_bytes);
  244.       if (mhnd2 == 0) 
  245.         return NULL;
  246.       adr2 = (unsigned char *) GlobalLock (mhnd2);
  247.       memcpy (adr2, ptr, (int) move_len);
  248.       W3LocalFree (ptr);
  249.       ptr = adr2;
  250.     } /* End of case where new one is too big for local */
  251.     }     /* End of cases where old block was local */
  252.   else      /* Always GlobalReAlloc if the memory was originally global */
  253.     {
  254.       if ((mhnd = LOWORD (GlobalHandle (HIWORD(ptr)))) == 0)
  255.     return NULL;
  256.       mhnd = GlobalReAlloc (mhnd, num_bytes, GMEM_MOVEABLE);
  257.       if (mhnd == 0) 
  258.     return NULL;
  259.       ptr = (unsigned char *) GlobalLock (mhnd);
  260.     } /* End of case where old one was global */
  261.   return ptr;
  262. }
  263. /* akin to free, returns memory alloced above
  264. */
  265. LOCAL void W3Free(unsigned char *ptr)
  266. {
  267.   HANDLE mhnd;
  268.   
  269.   W3CheckGlobalInit();
  270.   if (LOWORD((long)ptr) == 0) /* If memory is global */
  271.     {
  272.       if ((mhnd = LOWORD (GlobalHandle (HIWORD(ptr)))) == 0)
  273.     return ;
  274.       if (GlobalFree (mhnd) != 0)
  275.     return ;
  276.     }
  277.   else
  278.     W3LocalFree(ptr);
  279. }
  280. /* DEBUG ROUTINE TO CHECK HEAP STATE
  281. */
  282. LOCAL void *W3LocalCheck()
  283. {
  284. #ifndef PRODUCTION
  285.   W3_Zone *zone;
  286.   W3_Heap *h;
  287.   W3_MemBlk *b;
  288.   W3_QueEntry *hq, *q, *prev;
  289.   int size;
  290.  
  291. # ifdef SHAREABLE  
  292.   zone = W3FindZone (w3__zone);
  293. # else
  294.   zone = w3__zone;
  295. # endif
  296.  
  297.   /* Check that blocks haven't overrun other blocks 
  298.   */ 
  299.   for (hq = zone->heaps.next; hq != &(zone->heaps); hq = hq->next)
  300.     {
  301.       h = (W3_Heap *) ((char *)hq - sizeof(int));
  302.       for (b = &h->first;
  303.        (unsigned long) b < 
  304.        (unsigned long) W3_HEAP_ENDGUARDADDR (h, h->size);
  305.        b = W3NextMemBlk (b))
  306.         {
  307.       if ((b->size > -16) && (b->size < 16))
  308.             return b;
  309.       if (b->size > 0)
  310.             {
  311.           b->mark = 0;
  312.           size = b->size;
  313.           if ((b->link.prev->next != &b->link) ||
  314.           (b->link.next->prev != &b->link))
  315.                 return b;
  316.             }
  317.       else
  318.             size = -(b->size);
  319.       if (*(W3_MEMBLK_SIZEADDR (b, size)) != b->size)
  320.             return b;
  321.         }
  322.     }
  323.   
  324.   /* Check the integrity of the free list, marking free blocks that appear */
  325.   
  326.   prev = &zone->avail;
  327.   for (q = prev->next; q != &zone->avail; prev = q, q = q->next)
  328.     {
  329.       b = (W3_MemBlk *) ((char *)q-W3_MEMBLK_PREFIX);
  330.       if (b->size < 16)   /* Marked allocated */
  331.         return b;
  332.       b -> mark = 1;
  333.       if (q->prev != prev)
  334.     return b;
  335.     }
  336.   
  337.   /* Check the integrity of the randomizing pointer */
  338.   
  339.   b = (W3_MemBlk *) ((char *)zone->cur-W3_MEMBLK_PREFIX);
  340.   if (!b->mark)
  341.     return b;
  342.   
  343.   /* Check for "lost" free nodes, which don't appear in the free list      */
  344.   
  345.   for (hq = zone->heaps.next; hq != &zone->heaps; hq = hq->next)
  346.     {
  347.       h = (W3_Heap *) ((char *)hq - sizeof(int));
  348.       for (b = &h->first; (unsigned long) b < 
  349.        (unsigned long) W3_HEAP_ENDGUARDADDR (h, h->size); 
  350.        b = W3NextMemBlk (b))
  351.         if ((b->size > 0) && (b->mark != 1))
  352.       return b;
  353.     }
  354.   
  355.   /* The heap passed all tests */
  356.   
  357. #endif /* PRODUCTION */
  358.   return NULL;
  359. }
  360.  
  361. /************** Private support routines, can't be EXTERNED  ****************/
  362.  
  363. /* make memory into know block
  364. */
  365. STATIC W3_MemBlk  *W3FormMemBlk(void *addr, int size)
  366. {
  367.   W3_MemBlk *result;
  368.   
  369.   result = (W3_MemBlk *) addr;
  370.   result -> size = -size;
  371.   *W3_MEMBLK_SIZEADDR (result,size) = -size;
  372.   return result;
  373. }
  374. /* Split a free memory block in two, giving the first the specified size.
  375. */
  376. STATIC W3_MemBlk  *W3SplitMemBlk(W3_MemBlk *block, int size)
  377. {
  378.   W3_MemBlk *newblk;
  379.   int new_blksize;
  380.   
  381.   if ((block->size <= W3_MEMBLK_OVERHEAD) || (size <= W3_MEMBLK_OVERHEAD))
  382.     return NULL;
  383.   
  384.   new_blksize = block->size - size;
  385.   
  386.   newblk = (W3_MemBlk *) ((char *) block + size);
  387.   newblk->size = new_blksize;
  388.   *W3_MEMBLK_SIZEADDR (newblk,new_blksize) = new_blksize;
  389.   newblk->link.prev = &block->link;
  390.   newblk->link.next = block->link.next;
  391.   newblk->link.next->prev = &newblk->link;
  392.   newblk->link.prev->next = &newblk->link;
  393.   
  394.   block->size = size;
  395.   *W3_MEMBLK_SIZEADDR (block,size) = size;
  396.   
  397.   return newblk;
  398. }
  399. /* join adjacent memory if possible
  400. */
  401. STATIC W3_Boolean W3JoinMemBlks(W3_MemBlk *first, W3_MemBlk *second)
  402. {
  403.   if (((char *)second != (char *)first + first->size) ||
  404.       (second-> size <= W3_MEMBLK_OVERHEAD) ||
  405.       (first-> size <= W3_MEMBLK_OVERHEAD))
  406.     return FALSE;
  407.   
  408.   second->link.prev->next = second->link.next;
  409.   second->link.next->prev = second->link.prev;
  410.   first->size += second->size;
  411.   *W3_MEMBLK_SIZEADDR (first,first->size) = first->size;
  412.   return TRUE;
  413. }
  414. /* find a free blk in heap
  415. */
  416. STATIC W3_MemBlk  *W3FindMemBlk(W3_QueEntry *q, int size,
  417.                      W3_QueEntry *dummy)
  418. {
  419.   W3_QueEntry *p;
  420.   W3_MemBlk *curblock;
  421.   
  422.   for (p = q->next; ; p = p->next)
  423.     {
  424.       if (p != dummy)    /* Skip over listhead */
  425.     {
  426.       curblock = (W3_MemBlk *) ((char *)p-W3_MEMBLK_PREFIX);
  427.       if (curblock->size >= size)
  428.         return curblock;
  429.     }
  430.       if (p == q)
  431.     break;
  432.     }
  433.   return NULL;
  434. }
  435. /* insert a block into the free list, marking it as free.
  436.  */
  437. STATIC void       W3InsertMemBlk(W3_MemBlk *block, W3_QueEntry *q)
  438. {
  439.   block->size = -block->size;
  440.   *W3_MEMBLK_SIZEADDR(block,block->size) = block->size;
  441.   
  442.   block->link.next = q;
  443.   block->link.prev = q->prev;
  444.   block->link.next->prev = &block->link;
  445.   block->link.prev->next = &block->link;
  446. }
  447. /* allocate a blk of memory
  448. */
  449. STATIC void       W3RemoveMemBlk(W3_MemBlk *block)
  450. {
  451.   block->size = -block->size;
  452.   *W3_MEMBLK_SIZEADDR(block,(-block->size)) = block->size;
  453.   block->link.prev->next = block->link.next;
  454.   block->link.next->prev = block->link.prev;
  455. }
  456. /* find next blk
  457. */
  458. STATIC W3_MemBlk *W3NextMemBlk(W3_MemBlk *curr)
  459. {
  460.   int size;
  461.   
  462.   size = curr->size;
  463.   if (size < 0) 
  464.     size = -size;
  465.   return (W3_MemBlk *) ((char *)curr+size);
  466. }
  467. /* find prev blk
  468. */
  469. STATIC W3_MemBlk *W3PrevMemBlk(W3_MemBlk *curr)
  470. {
  471.   int size;
  472.   
  473.   size = *(int *)((char *)curr-W3_MEMBLK_SUFFIX);
  474.   if (size < 0) 
  475.     size = -size;
  476.   return (W3_MemBlk *) ((char *)curr-size);
  477. }
  478. /* create a heap, insert into list
  479. */
  480. STATIC W3_MemBlk *W3CreateHeap(int size, W3_QueEntry *after)
  481. {
  482.   W3_Heap *result;
  483.   
  484.   {
  485.     HANDLE     mhnd;
  486.     
  487.     mhnd = GlobalAlloc (GMEM_MOVEABLE, (unsigned long) size);
  488.     if (mhnd == 0)
  489.       result = NULL;
  490.     else
  491.       result = (W3_Heap *) GlobalLock (mhnd);
  492.   }
  493.   
  494.   if (result == NULL)
  495.     return NULL;
  496.   result->size = size;
  497.   result->link.prev = after;
  498.   result->link.next = after->next;
  499.   result->link.next->prev = &result->link;
  500.   result->link.prev->next = &result->link;
  501.   
  502.   W3FormMemBlk (&result->guard, W3_MEMBLK_OVERHEAD);
  503.   W3FormMemBlk (&result->first, size-W3_HEAP_OVERHEAD);
  504.   W3FormMemBlk (W3_HEAP_ENDGUARDADDR(result,size), W3_MEMBLK_OVERHEAD);
  505.   
  506.   return &result->first;
  507. }
  508. /* destroy heap, remove from list
  509. */
  510. STATIC void W3DestroyHeap(W3_Heap *heap)
  511. {
  512.   HANDLE mhnd;
  513.  
  514.   heap->link.prev->next = heap->link.next;
  515.   heap->link.next->prev = heap->link.prev;
  516.   if ((mhnd = LOWORD (GlobalHandle (HIWORD(heap)))) != 0)
  517.     GlobalFree (mhnd);
  518. }
  519. /* return if entire heap is one unused blk
  520. */
  521. STATIC W3_Boolean W3HeapIsEmpty(W3_Heap *heap)
  522. {
  523.   return (W3_Boolean)((heap->first.size) == (heap->size-W3_HEAP_OVERHEAD));
  524. }
  525. #ifdef SHAREABLE
  526. /* find zone of memory with requested if
  527. */
  528. STATIC W3_Zone *W3FindZone(W3_Zone *root, int id)
  529. {
  530.   W3_Zone *zone;
  531.   
  532.   for (zone = root; zone != NULL; zone = zone->next)
  533.     if (zone -> zone_id == id)
  534.       break;
  535.   return zone;
  536. }
  537. #endif
  538. /* create a zone of memory, possible marked with id
  539. */
  540. #ifdef SHAREABLE
  541.   W3_Zone *W3CreateZone (W3_Zone *root, int id)
  542. #else
  543.   W3_Zone *W3CreateZone (W3_Zone *root)
  544. #endif
  545. {
  546.   W3_Zone *zone;
  547.   HANDLE hZone;
  548.   
  549.   if (root == NULL)
  550.     {
  551.       hZone = LocalAlloc (LMEM_FIXED, sizeof (W3_Zone));
  552.       if (hZone == 0)
  553.         zone = NULL;
  554.       else
  555.         zone = (W3_Zone *) (LocalLock (hZone));
  556.     }
  557.   else
  558.     {
  559.       for (zone = root; zone->next != NULL; zone = zone->next)
  560.         ;
  561.       hZone = LocalAlloc (LMEM_FIXED, sizeof (W3_Zone));
  562.       if (hZone == 0)
  563.         zone = NULL;
  564.       else
  565.         zone -> next = (W3_Zone *) LocalLock (hZone);
  566.       zone = zone->next;
  567.     }
  568.   
  569.   if (zone == NULL)
  570.     return NULL;  
  571.   zone -> avail.prev = &(zone -> avail);
  572.   zone -> avail.next = &(zone -> avail);
  573.   zone -> heaps.prev = &(zone -> heaps);
  574.   zone -> heaps.next = &(zone -> heaps);
  575.   zone -> cur = &(zone -> avail);
  576.   zone -> next = NULL;
  577. #ifdef SHAREABLE
  578.   zone -> zone_id = id;
  579. #endif
  580.   return zone;
  581. }
  582. /* malloc memory from existing stores
  583. */
  584. STATIC void *W3LocalMalloc(int size)
  585. {
  586.   int actsize;
  587.   W3_MemBlk *temp;
  588.   W3_Zone *zone;
  589. #ifdef SHAREABLE
  590.   int zoneid;
  591.   
  592.   zoneid = GetCurrentTask();
  593.   
  594.   if ((zone = W3FindZone (w3__zone, zoneid)) == NULL)
  595.     if ((zone = W3CreateZone (w3__zone, zoneid)) == NULL)
  596.       return NULL;
  597. #else
  598.   if (!(zone = w3__zone))
  599.     if ((zone = W3CreateZone (w3__zone)) == NULL)
  600. #endif
  601.   
  602.   if (size > W3_MAX_SMALL_BLOCK-W3_MEMBLK_OVERHEAD)
  603.     return NULL;
  604.   
  605.   /* Leave room for overhead and ensure that no tiny fragments 
  606.   * which are too small to fit on the free list are generated.
  607.   */
  608.   actsize = W3_ROUNDSIZE (size + W3_MEMBLK_OVERHEAD);
  609.   temp = W3FindMemBlk (zone->cur, actsize, &(zone->avail));
  610.   if (temp == NULL)
  611.     {
  612.       temp = W3CreateHeap (W3_HEAP_INCREMENT, &(zone->heaps));
  613.       if (temp == NULL)
  614.         return NULL;
  615.       W3InsertMemBlk (temp, zone->cur);
  616.     }
  617.   if (temp->size > actsize + W3_MEMBLK_OVERHEAD) /* If it can be split */
  618.     W3SplitMemBlk (temp, actsize);
  619.   
  620.   zone->cur = temp->link.prev;
  621.   
  622.   W3RemoveMemBlk (temp);
  623.   return ((void *) (&temp->link));
  624. }
  625. /* realloc memory from existing stores
  626. */
  627. STATIC void *W3LocalRealloc(void *curaddr, int newsize)
  628. {
  629.   W3_MemBlk *curr, *newblk;
  630.   W3_Zone *zone;
  631.   char *newmem;
  632.   int adjsize, incr;
  633.  
  634. #ifdef SHAREABLE  
  635.   if ((zone = W3FindZone (w3__zone, GetCurrentTask())) == NULL)
  636.     return NULL;
  637. #else
  638.   if (!(zone = w3__zone))
  639.     return NULL;
  640. #endif
  641.   if (newsize > W3_MAX_SMALL_BLOCK-W3_MEMBLK_OVERHEAD)
  642.     return NULL;
  643.   
  644.   curr = (W3_MemBlk *) ((char *)curaddr - W3_MEMBLK_PREFIX);
  645.   if (curr->size > 0)  /* If the block is free, go no further */
  646.     return NULL;
  647.   
  648.   adjsize = W3_ROUNDSIZE (newsize + W3_MEMBLK_OVERHEAD);
  649.   incr = adjsize - (-curr->size);  /* remember - curr->size is negative */
  650.   
  651.   /* If the request is enough less than the current 
  652.   * allocation, free space 
  653.   */
  654.   if (incr < 0)
  655.     {
  656.       curr->size = curr->size - incr;
  657.       *W3_MEMBLK_SIZEADDR(curr, -curr->size) = curr->size;
  658.       newblk = W3FormMemBlk ((char *)curr - curr->size, -incr);
  659.       W3InsertMemBlk (newblk, zone->cur);
  660.     }
  661.   
  662.   /* If caller wants more space & the next block is big 
  663.   * enough & free, use it 
  664.   */
  665.   if (incr > 0)
  666.     {
  667.       newblk = W3NextMemBlk (curr);
  668.       if (newblk->size > (2 * incr))  /* Too big to sacrifice the whole thing */
  669.         W3SplitMemBlk (newblk, incr);
  670.       
  671.       if (newblk->size >= incr)
  672.     {
  673.       zone->cur = newblk->link.prev;
  674.       newblk->link.prev -> next = newblk->link.next;
  675.       newblk->link.next -> prev = newblk->link.prev;
  676.       curr->size -= newblk->size;
  677.       *W3_MEMBLK_SIZEADDR (curr,-curr->size) = curr->size;
  678.     }
  679.       else    /* No such luck. We have to move the data */
  680.     {
  681.       newmem = W3LocalMalloc (newsize);
  682.       if (newmem == NULL)
  683.         curaddr = NULL;
  684.       else
  685.         {
  686.           memcpy (newmem, curaddr, (-curr->size)-W3_MEMBLK_OVERHEAD);
  687.           W3LocalFree (curaddr);
  688.           curaddr = newmem;
  689.         }
  690.     }
  691.     }
  692.   
  693.   /* Case when only a very little is being trimmed is 
  694.   * handled implicitly i.e. do nothing 
  695.   */
  696.   return curaddr;
  697.   
  698. }
  699. /* calloc memory from local stores
  700. */
  701. STATIC void *W3LocalCalloc (int items, int size)
  702. {
  703.   void *temp;
  704.   
  705.   temp = W3LocalMalloc (items * size);
  706.   if (temp != NULL)
  707.     memset (temp, '\0', items * size);
  708.   return temp;
  709. }
  710. /* free memory allocated from local stores
  711. */
  712. STATIC void  W3LocalFree(void *addr)
  713. {
  714.   W3_MemBlk *block, *other;
  715.   W3_Zone *zone;
  716.   W3_Heap *heap;
  717.  
  718. #ifdef SHAREABLE  
  719.   if ((zone = W3FindZone (w3__zone, GetCurrentTask())) == NULL)
  720.     return;
  721. #else
  722.   if (!(zone = w3__zone))
  723.     return;
  724. #endif
  725.   block = (W3_MemBlk *) ((char *)addr - W3_MEMBLK_PREFIX);
  726.   W3InsertMemBlk (block, &(zone->avail));
  727.   W3JoinMemBlks(block, 
  728.            W3NextMemBlk(block)); /* Joins check before joining */
  729.   other = W3PrevMemBlk(block);        /* so just try it and see     */
  730.   if (W3JoinMemBlks(other, block))
  731.     zone->cur = other->link.next;
  732.   else
  733.     zone->cur = block->link.next;
  734.  
  735.   heap = (W3_Heap *)((unsigned long)block & 0xFFFF0000L); /* Hack works */
  736.   if (W3HeapIsEmpty (heap))
  737.     {
  738.       W3RemoveMemBlk (&heap->first);
  739.       W3DestroyHeap (heap);
  740.     }
  741. }
  742. /* return avali size at address
  743. */
  744. STATIC int W3LocalSize(void *addr)
  745. {
  746.   W3_MemBlk *block;
  747.   int size;
  748.   
  749.   block = (W3_MemBlk *) ((char *)addr - W3_MEMBLK_PREFIX);
  750.   size = (block->size > 0) ? block->size : -block->size;
  751.   size -= W3_MEMBLK_OVERHEAD;
  752.   return size;
  753. }
  754.  
  755. /****************************************************************************
  756. * Memory management functions REPLACING C-runtime malloc, calloc, 
  757. * realloc and free. Only for use ifndef SHAREABLE. #define MAGIC, etc
  758. * to build guard code during debugging. If this module built as DLL,
  759. * then need to make W3Malloc, W3Calloc, W3Realloc and W3Free calls instead.
  760. *
  761. * Defining MAGIC requires fleshing out localprintf and localbeep (notGNU
  762. * provides entry points when linked/compiled nonshareable into notGNU.exe)
  763. *
  764. *****************************************************************************/
  765. #ifndef SHAREABLE
  766.  
  767. /* TO TURN ON MEMORY MANAGLEMENT CHECKING...
  768. */
  769. #define    MAGIC        0x4d4d4d4dL
  770. #define    OLDMAGIC    0x46464646L
  771. #define CRASH        0x55
  772. #define NEWMEM        0x45
  773.  
  774. #define localprintf    ewprintf
  775. #define localbeep    ttbeep
  776.  
  777. /* COMMENT OUT TO TURN OFF */
  778.  
  779. /* Struct at head of allocated block. Single GUARD word
  780. * appended at end as well.
  781. */
  782. typedef unsigned int GUARD;
  783. typedef struct _chunk
  784.   {
  785.     GUARD magic;
  786.     long nbytes;
  787.   } Chunk;
  788.  
  789. #define nChunk        sizeof(Chunk)
  790. #define nEnd            sizeof(GUARD)
  791. #define Mem(pmem_)    (Chunk *)(((char *)pmem_ - nChunk))
  792. #define End(p, q)       (GUARD *)((char *)p + q->nbytes)
  793.  
  794. /* Capture entry points; caller code thinks this is C runtime!
  795. */
  796. void CDECL free(void FAR *p)
  797. {
  798. #ifdef MAGIC
  799.   Chunk *q;
  800.   GUARD *eguard;
  801.  
  802.   if (!p)
  803.     {
  804.       localprintf("Free: pointer is NULL!");
  805.       localbeep();
  806.       sleep(1);
  807.       return;  
  808.     }
  809.  
  810.   q = Mem(p);
  811.   eguard = End(p, q);
  812.  
  813.   if (q->magic != (GUARD)MAGIC)
  814.     {
  815.       if (q->magic == (GUARD)OLDMAGIC)
  816.         localprintf("Free: memory already freed!");
  817.       else
  818.         localprintf("Free: front guard gone!");
  819.       localbeep();
  820.       sleep(1);
  821.       return;
  822.     }
  823.  
  824.   if (*eguard != (GUARD)MAGIC)
  825.     {
  826.       localprintf("Free: end guard gone!");
  827.       localbeep();
  828.       sleep(1);
  829.       return;
  830.     }
  831.  
  832.   memset(p, CRASH, (size_t)q->nbytes);    /* make it useless */
  833.   q->magic = (GUARD)OLDMAGIC;        /* mark freed */
  834.   p = q;                /* free the real allocated block */
  835. #endif  /* MAGIC */
  836.   W3Free((unsigned char *)p);
  837. }
  838. void * CDECL malloc(size_t n)
  839. {
  840. #ifdef MAGIC
  841.   Chunk *q;
  842.   char *p;
  843.   
  844.   q = (Chunk *)W3Malloc((unsigned long)n + nChunk + nEnd);
  845.   p = (char *)q;
  846.   if (p)
  847.     {
  848.       GUARD *eguard;
  849.  
  850.       q->magic = (GUARD)MAGIC;
  851.       q->nbytes = (long)n;
  852.       p += nChunk;            /* user pointer value */
  853.       eguard = End(p, q);
  854.       *eguard = (GUARD)MAGIC;
  855.     }
  856.   memset(p, NEWMEM, n);      
  857.   return (p);
  858. #else /* MAGIC */
  859.   return (W3Malloc((unsigned long)n));
  860. #endif /* MAGIC */
  861. }
  862. void * CDECL calloc(size_t c, size_t n)
  863. {
  864. #ifdef MAGIC
  865.   char *p = malloc(c * n);
  866.  
  867.   if (p)
  868.     memset(p, 0, c * n);
  869.   return (p);
  870. #else /* MAGIC */
  871.   return(W3Calloc((unsigned long)c, (unsigned long)n));
  872. #endif /* MAGIC */
  873. }
  874. void * CDECL realloc(void FAR * p, size_t n)
  875. {
  876. #ifdef MAGIC
  877.   Chunk *q;
  878.   char *s;
  879.   GUARD *eguard;
  880.  
  881.   q = Mem(p);
  882.   eguard = End(p, q);
  883.  
  884.   if (q->magic != (GUARD)MAGIC)
  885.     {
  886.       if (q->magic == (GUARD)OLDMAGIC)
  887.         localprintf("Realloc: memory freed!");
  888.       else 
  889.         localprintf("Realloc: no front guard!");
  890.       localbeep();
  891.       sleep(1);
  892.     }
  893.  
  894.   if (*eguard != (GUARD)MAGIC)
  895.     {
  896.       localprintf("Realloc: no end guard!");
  897.       localbeep();
  898.       sleep(1);
  899.     }
  900.  
  901.   /* cheap, realloc smaller doesn't do anything!
  902.   */
  903.   if (q->nbytes <= (long)n)
  904.     return(p);
  905.  
  906.   s = malloc(n);
  907.   if (!s)
  908.     {
  909.       free(p);
  910.       return(NULL);
  911.     }
  912.  
  913.   /* move used bytes to new block, free old block
  914.   */  
  915.   memcpy(s, p, (size_t)(q->nbytes));    /* know that old size was smaller */
  916.   free(q);                /* free actual allocated block */
  917.   return(s);
  918. #else
  919.   return (W3Realloc((unsigned char *)p, (unsigned long)n));
  920. #endif
  921. }
  922. #endif /* ~SHAREABLE */
  923.  
  924. #endif /* whole file */
  925.